package colopl.http.service;

import gae.util.http.client.HttpRequest;
import gae.util.http.client.HttpResponse;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import colopl.http.client.ColoplHttpRequestFactory;
import colopl.http.client.ColoplHttpRequestUtil;
import colopl.http.client.ColoplUser;
import colopl.http.service.bean.LinkColony;
import colopl.http.service.bean.PlantBlock;
import colopl.http.service.bean.ColoplResult;
import colopl.http.service.bean.SouvenirCount;
import colopl.http.service.bean.WareHouseItem;
import colopl.http.util.MessageResource;
import colopl.http.util.RegexUtil;

public class ColoplServiceImpl implements ColoplService {
    
    private static final Log logger = LogFactory.getLog(ColoplServiceImpl.class);
    
    private ColoplHttpRequestFactory factory = new ColoplHttpRequestFactory();
    
    private final static String autoIDRegexp = "<a href=\"itemOperateWH\\.do\\?id=[1-9][0-9]*&amp;uid=.+&amp;guid=ON&autoID=([1-9][0-9]*)\">";
    
    private final static String nameRegexp = "<a href=\"itemOperateWH\\.do\\?id=[1-9][0-9]*&amp;uid=.+&amp;guid=ON&autoID=[1-9][0-9]*\">(.+)</a><br/>";
    
    private final static String pointRegexp = "<a href=\"itemWH\\.do\\?id=[1-9][0-9]*&amp;uid=.+&amp;guid=ON&amp;point=([0-9]*)\">";
    
    private final static String linkcolonieRegexp = "<a href=\"mainOther.do\\?id=[1-9][0-9]*&amp;uid=.+&amp;guid=ON&toID=([1-9][0-9]*)\">第[1-9][0-9]*ｺﾛﾆｰ</a>\n";
    
    private final static String nicknameRegexp = "<a href=\"mainOther.do\\?id=[1-9][0-9]*&amp;uid=.+&amp;guid=ON&toID=[1-9][0-9]*\">第[1-9][0-9]*ｺﾛﾆｰ</a>\n"
            + "(?:(?:(?:\t\n\t\n\t|\t\t\t\n\t\t\t|\t)\\((.+)\\))|(?:(?:\t\n\t|\t\t\t)(?:<br>|<img)))";
    
    private final static String omiyageIDRegexp = "<option value=\"([0-9]*)\">自[0-9]*相[0-9]*&nbsp;";
    
    private final static String myCountRegexp = "<option value=\"[0-9]*\">自([0-9]*)相[0-9]*&nbsp;";
    
    private final static String otherCountRegexp = "<option value=\"[0-9]*\">自[0-9]*相([0-9]*)&nbsp;";
    
    private final static String souvenirNameRegexp = "<option value=\"[0-9]*\">自[0-9]*相[0-9]*&nbsp;(.+)</option>";
    
    
    
    @Override
    public List<WareHouseItem> getWareHouseItems(ColoplUser user) throws ColoplServiceException {
        List<WareHouseItem> items = new ArrayList<WareHouseItem>();
        
        // 倉庫の１ページ目にアクセス
        HttpRequest req = factory.createWHItem(user, 0);
        HttpResponse res = null;
        try {
            res = req.execute();
        } catch (IOException e1) {
            throw new ColoplServiceException(MessageResource.getMessage("CHC-201", req), e1);
        }
        ColoplHttpRequestUtil.updateCookie(user, res);
        
        // HTMLをパース
        List<String> autoIDs = new ArrayList<String>();
        List<String> names = new ArrayList<String>();
        List<String> pages = new ArrayList<String>();
        
        RegexUtil regex = new RegexUtil();
        regex.addRegex(autoIDRegexp, autoIDs);
        regex.addRegex(nameRegexp, names);
        regex.addRegex(pointRegexp, pages);
        try {
            regex.parse(res.getConnection().getInputStream());
        } catch (IOException e1) {
            throw new ColoplServiceException(MessageResource.getMessage("CHC-202", res), e1);
        } finally {
            if (logger.isDebugEnabled()) {
                logger.debug("autoIDs=" + autoIDs + ", names=" + names + ",pages=" + pages);
            }
            res.getConnection().disconnect();
        }
        
        // Beanの作成
        items.addAll(BeanUtil.convertWareHouseItem(autoIDs, names, 1));
        
        // 倉庫サイズの取得
        int pageSize = 0;
        try {
            pageSize = Integer.valueOf(pages.get(pages.size() - 1));
        } catch (NumberFormatException e) {
            // 1ページしかない
        }
        
        // 倉庫サイズの数だけ繰り返す
        for (int i = 1; i < pageSize + 1; i++) {
            HttpRequest req2 = factory.createWHItem(user, 1);
            HttpResponse res2 = null;
            try {
                res2 = req2.execute();
            } catch (IOException e1) {
                throw new ColoplServiceException(MessageResource.getMessage("CHC-201", req2), e1);
            }
            ColoplHttpRequestUtil.updateCookie(user, res2);
            
            List<String> autoIDs2 = new ArrayList<String>();
            List<String> names2 = new ArrayList<String>();
            
            // HTMLをパース
            RegexUtil regex2 = new RegexUtil();
            regex2.addRegex(autoIDRegexp, autoIDs2);
            regex2.addRegex(nameRegexp, names2);
            try {
                regex2.parse(res2.getConnection().getInputStream());
            } catch (IOException e1) {
                throw new ColoplServiceException(MessageResource.getMessage("CHC-202", res2), e1);
            } finally {
                if (logger.isDebugEnabled()) {
                    logger.debug("autoIDs2=" + autoIDs + ", names2=" + names2);
                }
                res2.getConnection().disconnect();
            }
            
            // Beanを追加
            items.addAll(BeanUtil.convertWareHouseItem(autoIDs2, names2, i + 1));
        }
        
        return items;
    }

//    @Override
    public List<WareHouseItem> getWareHouseItems(ColoplUser user, String subname)
            throws ColoplServiceException {
        
        List<WareHouseItem> list = new ArrayList<WareHouseItem>();
        
        String[] subnames = subname.split(" ");
        
        Iterator<WareHouseItem> ite = this.getWareHouseItems(user).iterator();
        while (ite.hasNext()) {
            WareHouseItem item = ite.next();
            boolean isMatch = true;
            for (int i = 0; i < subnames.length; i++) {
                if (!item.getName().toLowerCase().contains(subnames[i].toLowerCase())) {
                    isMatch = false;
                    break;
                }
            }
            if (isMatch) {
                list.add(item);
            }
        }
        
        return list;
    }


    @Override
    public List<LinkColony> getLinkColonies(ColoplUser user, String section,
            int groupId) throws ColoplServiceException {
        
        List<LinkColony> list = new ArrayList<LinkColony>();
        
        // リンクコロニーのページにアクセス
        HttpRequest req = factory.createLinkGroup(user, section, groupId);
        HttpResponse res = null;
        String body = null;
        try {
            res = req.execute();
            body = res.getBodyToString("UTF-8");
        } catch (IOException e1) {
            throw new ColoplServiceException(MessageResource.getMessage("CHC-203", req), e1);
        }
        ColoplHttpRequestUtil.updateCookie(user, res);
        
        // HTMLをパース
        List<String> ids = new ArrayList<String>();
        List<String> nicknames = new ArrayList<String>();
        
        ids.addAll(RegexUtil.extractAll(linkcolonieRegexp, body));
        nicknames.addAll(RegexUtil.extractAll(nicknameRegexp, body));
        
        if (ids.size() != nicknames.size()) {
            throw new ColoplServiceException(MessageResource.getMessage("CHC-204", ids, nicknames, res));
        }
        
        // Beanの作成
        list.addAll(BeanUtil.convertLinkColony(ids, nicknames, section, groupId));
        
        return list;
    }

    @Override
    public List<SouvenirCount> getSouvenirCounts(ColoplUser user, int toID, int area) 
            throws ColoplServiceException {
        
        List<SouvenirCount> list = new ArrayList<SouvenirCount>();
        
        // お土産選択画面にアクセス
        HttpRequest req = factory.createPresentOmiyage(user, toID, area);
        HttpResponse res = null;
        try {
            res = req.execute();
        } catch (IOException e1) {
            throw new ColoplServiceException(MessageResource.getMessage("CHC-205", req), e1);
        }
        ColoplHttpRequestUtil.updateCookie(user, res);
        
        // HTMLをパース
        List<String> omiyageIDs = new ArrayList<String>();
        List<String> myCounts = new ArrayList<String>();
        List<String> otherCounts = new ArrayList<String>();
        List<String> names = new ArrayList<String>();

        RegexUtil regex = new RegexUtil();
        regex.addRegex(omiyageIDRegexp, omiyageIDs);
        regex.addRegex(myCountRegexp, myCounts);
        regex.addRegex(otherCountRegexp, otherCounts);
        regex.addRegex(souvenirNameRegexp, names);
        try {
            regex.parse(res.getConnection().getInputStream());
        } catch (IOException e1) {
            throw new ColoplServiceException(MessageResource.getMessage("CHC-206", omiyageIDs, myCounts, otherCounts, names, res), e1);
        } finally {
            res.getConnection().disconnect();
        }
        
        // Beanの作成
        list.addAll(BeanUtil.convertSouvenirCount(omiyageIDs, myCounts, otherCounts, names));
        
        return list;
    }


    @Override
    public List<ColoplResult<Integer>> presentSouvenirs(ColoplUser user,
            List<Integer> omiyageIDs, int area, int toID, int num) {
        
        List<ColoplResult<Integer>> list = new ArrayList<ColoplResult<Integer>>();
        
        for (int i = 0; i < omiyageIDs.size(); i++) {
            ColoplResult<Integer> result = new ColoplResult<Integer>();
            result.setObject(omiyageIDs.get(i));
            try {
                
                // お土産をプレゼント
                HttpRequest req = factory.createPresentOmiyageDo(user, toID, area, omiyageIDs.get(i), num);
                HttpResponse res = null;
                try {
                    res = req.execute();
                } catch (IOException e1) {
                    throw new ColoplServiceException(MessageResource.getMessage("CHC-207", res), e1);
                }
                ColoplHttpRequestUtil.updateCookie(user, res);
                
                // 結果を確認
                String body = res.getBodyToString("UTF-8");
                if (body.contains("プレゼントしました。")) {
                    result.setSuccessful(true);
                } else {
                    result.setException(new ColoplServiceException(MessageResource.getMessage("CHC-208", omiyageIDs.get(i), res)));
                }
                
            } catch (Exception e) {
                result.setException(e);
            }
            list.add(result);
        }
        
        return list;
    }

    @Override
    public List<ColoplResult<PlantBlock>> buildPlants(ColoplUser user,
            List<PlantBlock> plants) {
        
        List<ColoplResult<PlantBlock>> list = new ArrayList<ColoplResult<PlantBlock>>();
        
        for (int i = 0; i < plants.size(); i++) {
            ColoplResult<PlantBlock> result = new ColoplResult<PlantBlock>();
            PlantBlock plant = plants.get(i);
            result.setObject(plant);
            try {
                
                // 建造
                HttpRequest req = factory.createBuildBatchDo(user, 
                        plant.getSerial(), 
                        plant.getX(), plant.getY(), 
                        plant.getX2(), plant.getY2(), 
                        plant.getAction());
                HttpResponse res = null;
                try {
                    res = req.execute();
                } catch (IOException e1) {
                    throw new ColoplServiceException(MessageResource.getMessage("CHC-209", req), e1);
                }
                ColoplHttpRequestUtil.updateCookie(user, res);
                
                // 結果を確認
                List<String> locations = res.getHeader().get("Location");
                if (locations != null && locations.size() > 0
                        && locations.get(0).startsWith("http://colopl.jp/s/buildBatchInst.do?id=")) {
                    result.setSuccessful(true);
                } else {
                    result.setException(new ColoplServiceException(MessageResource.getMessage("CHC-210", plant, res)));
                }
                
            } catch (Exception e) {
                result.setException(e);
            }
            list.add(result);
        }
        
        return list;
    }


    @Override
    public List<ColoplResult<Integer>> updateWareHouseItemInfos(ColoplUser user,
            List<Integer> autoIDs, int priority, String msg, int price) {
        
        List<ColoplResult<Integer>> list = new ArrayList<ColoplResult<Integer>>();
        
        for (int i = 0; i < autoIDs.size(); i++) {
            ColoplResult<Integer> result = new ColoplResult<Integer>();
            result.setObject(autoIDs.get(i));
            try {
                
                // 倉庫アイテムの情報を更新
                HttpRequest req = factory.createItemSetWHAction(user, autoIDs.get(i), priority, msg, price);
                HttpResponse res = null;
                try {
                    res = req.execute();
                } catch (IOException e1) {
                    throw new ColoplServiceException(MessageResource.getMessage("CHC-211", req), e1);
                }
                ColoplHttpRequestUtil.updateCookie(user, res);
                
                // 結果を確認
                String body = res.getBodyToString("UTF-8");
                if (body.contains("設定しました。")) {
                    result.setSuccessful(true);
                } else {
                    result.setException(new ColoplServiceException(MessageResource.getMessage("CHC-212", res)));
                }
                
            } catch (Exception e) {
                result.setException(e);
            }
            list.add(result);
        }
        
        return list;
    }
    
    

}
